package com.ctw.tinyservices.id.core.segment.buffer;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author TongWei.Chen 2022/3/9 19:52
 *
 * 号段缓冲区
 **/
public class SegmentBuffer {

    /**
     * 业务类型
     */
    private String bizType;

    /**
     * 双buffer
     */
    private Segment[] segments;

    /**
     * 当前的使用的Segment的下标
     */
    private volatile int currentPos;

    /**
     * 下一个号段是否准备完毕，也就是说当一个号段写满后，下一个Segment是否处于可切换状态
     */
    private volatile boolean nextReady;

    /**
     * 线程是否在运行中，写号段的时候用
     */
    private final AtomicBoolean threadRunning;

    /**
     * 采取读写锁提高并发
     */
    private final ReadWriteLock lock;

    public SegmentBuffer() {
        segments = new Segment[]{new Segment(), new Segment()};
        currentPos = 0;
        nextReady = false;
        threadRunning = new AtomicBoolean(false);
        lock = new ReentrantReadWriteLock();
    }

    public Segment getCurrent() {
        return segments[currentPos];
    }

    /**
     * 切换下一个号段
     * @return
     */
    public int nextPos() {
        return (currentPos + 1) & 1;
    }

    public void switchPos() {
        currentPos = nextPos();
    }

    public Lock rLock() {
        return lock.readLock();
    }

    public Lock wLock() {
        return lock.writeLock();
    }

    public String getBizType() {
        return bizType;
    }

    public void setBizType(String bizType) {
        this.bizType = bizType;
    }

    public Segment[] getSegments() {
        return segments;
    }

    public void setSegments(Segment[] segments) {
        this.segments = segments;
    }

    public int getCurrentPos() {
        return currentPos;
    }

    public void setCurrentPos(int currentPos) {
        this.currentPos = currentPos;
    }

    public boolean isNextReady() {
        return nextReady;
    }

    public void setNextReady(boolean nextReady) {
        this.nextReady = nextReady;
    }

    public AtomicBoolean getThreadRunning() {
        return threadRunning;
    }

    public ReadWriteLock getLock() {
        return lock;
    }
}
